package com.raos.caffeine;

import com.raos.caffeine.utils.CaffeineUtils;
import com.raos.caffeine.utils.SpringUtils;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import static com.raos.caffeine.config.CaffeineConfig.*;

/**
 * caffeine 缓存控制器
 *
 * @author raos
 * @email 991207823@qq.com
 */
@SuppressWarnings("all")
@RestController
@RequestMapping("/caffeine")
public class CaffeineController {

    private static final String CACHE_NAME = "forlan";

    @Resource(name = "caffeineCacheManager")
    private CacheManager cacheManager;
    @Resource
    private RedisTemplate redisTemplate;

    /***
     * 依据key获取缓存数据（方式1：@Cacheable注解方式）
     * 注意：@Cacheable注解，在方法上，表示该方法的返回结果是可以缓存的。
     *      也就是说，该方法的返回结果会放在缓存中，以便于以后使用相同的参数调用该方法时，会返回缓存中的值，而不会实际执行该方法。
     * @param key 键
     * @return 数据
     */
    @PostMapping("/get")
    @Cacheable(value = CACHE_NAME)
    public Object get(@RequestParam("key") String key) {
        Object data = key;
        return "当前时间为" + LocalDateTime.now() + "，获取的内容为：" + data;
    }

    /***
     * 依据key-value设置缓存数据（方式2：cacheManager 缓存管理器）
     * @param key,value 键,值
     * @return 数据
     */
    @PostMapping("/setCaffeine")
    public Object setCaffeine1(@RequestParam("key") String key, @RequestParam("value") String value) {
        Cache caffeineCache = cacheManager.getCache(CACHE_NAME);
        value = "插入时间为" + LocalDateTime.now() + "，插入的内容为：" + value;
        caffeineCache.put(key, value);
        return "ok";
    }

    /***
     * 依据key获取缓存数据（方式2：cacheManager 缓存管理器）
     * @param key 键
     * @return 数据
     */
    @PostMapping("/getCaffeine")
    public Object getCaffeine1(@RequestParam("key") String key) {
        Cache caffeineCache = cacheManager.getCache(CACHE_NAME);
        Object data;
        try {
            data = caffeineCache.get(key).get();
        } catch (Exception e) {
            e.getStackTrace();
            data = "缓存失效，未找到！";
        }
        return "当前时间为" + LocalDateTime.now() + "，获取的内容为：" + data;
    }

    /* 使用spring工具类设置或获取缓存 */

    @PostMapping("/setCaffeine2")
    public String setCaffeine2(@RequestParam("key") String key, @RequestParam("value") String value) {
        com.github.benmanes.caffeine.cache.Cache<String, Object> caffeine =
                (com.github.benmanes.caffeine.cache.Cache<String, Object>) SpringUtils.getBean(ONE_CACHE_NAME);
        value = "插入时间为" + System.nanoTime() + "，插入的内容为：" + value;
        caffeine.put(key, value);
        return "ok";
    }

    @PostMapping("/getCaffeine2")
    public Object getCaffeine2(@RequestParam("key") String key) {
        com.github.benmanes.caffeine.cache.Cache<String, Object> caffeine =
                (com.github.benmanes.caffeine.cache.Cache<String, Object>) SpringUtils.getBean(ONE_CACHE_NAME);
        Object value = caffeine.asMap().get(key);
        value = value == null ? "缓存失效，未找到！" : value;
        return value;
    }

    /* 使用Caffeine工具类设置或获取缓存 */

    @PostMapping("/setCaffeine3")
    public String setCaffeine3(@RequestParam("key") String key, @RequestParam("value") String value) {
        value = "插入时间为" + System.nanoTime() + "，插入的内容为：" + value;
        CaffeineUtils.put(key, value);
        return "ok";
    }

    @PostMapping("/getCaffeine3")
    public Object getCaffeine3(@RequestParam("key") String key) {
        Object value = CaffeineUtils.get(key);
        value = value == null ? "缓存失效，未找到！" : value;
        return value;
    }

    /* Caffeine+Redis 实现二级缓存 */

    @PostMapping("/get2")
    @Cacheable(value = CACHE_NAME)
    public Object get2(@RequestParam("key") String key) {
        Object data = null;
        if (redisTemplate.hasKey(key)) {
            data = redisTemplate.opsForValue().get(key);
        } else {
            data = "新建内容，纳秒时间：" + System.nanoTime();
            redisTemplate.opsForValue().set(key, data);
        }
        return "当前时间为" + LocalDateTime.now() + "，获取的内容为：" + data;
    }


}
